# 子进程要执行的代码
import os
import random
import threading
from multiprocessing import Process
#
# # 1.进程
import time
from multiprocessing.pool import Pool
from queue import Queue


def run_proc(name):
    print('Run child process %s (%s)...' % (name, os.getpid()))


if __name__ == '__main__':
    print('Parent process %s.' % os.getpid())
    p = Process(target=run_proc, args=('test',))
    p.start()
    p.join()


# 2.进程池
def long_time_task(name):
    print('Run task %s (%s)...' % (name, os.getpid()))
    start = time.time()
    print('Task %s runs %0.2f seconds.' % (name, start))


if __name__ == '__main__':
    p = Pool(4)
    for i in range(5):
        p.apply_async(long_time_task, args=(i,))
    p.close()
    p.join()


# 3.进程间通信
# 写数据进程执行的代码:

def write(q):
    print('写数据 Process to write: %s' % os.getpid())
    q.put("写入的数据")
    time.sleep(random.random())  # 读数据进程执行的代码:


def read(q):
    print('读数据 Process to read: %s' % os.getpid())
    value = q.get(True)
    while (True):
        print('Get %s from queue.' % value, os.getpid())


if __name__ == '__main__':
    # 父进程创建Queue，并传给各个子进程：
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 启动子进程pw，写入:
    pw.start()
    # 启动子进程pr，读取:
    pr.start()
    # 等待pw结束:
    pw.join()
    # pr进程里是死循环，无法等待其结束，只能强行终止:
    pr.terminate()


# 4.多线程
def run_thread(n):
    for i in range(30):
        time.sleep(1)
        print(n)


t1 = threading.Thread(target=run_thread, args=("第一个线程",), name='Thread-A')
t2 = threading.Thread(target=run_thread, args=("第二个线程",), name='Thread-B')
# t1.start()
# t2.start()
# t1.join()
# t2.join()


# 5.hreadLocal
# 一个ThreadLocal变量虽然是全局变量，但每个线程都只能读写自己线程的独立副本，互不干扰
# 。ThreadLocal解决了参数在一个线程中各个函数之间互相传递的问题。
# 创建全局ThreadLocal对象:
local_school = threading.local()
def process_thread(name):
    # 绑定ThreadLocal的student:
    local_school.student = name
    # 获取当前线程关联的student:
    std = local_school.student
    print('Hello, %s (in %s)' % (std, threading.current_thread().name))

t1 = threading.Thread(target=process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target=process_thread, args=('Bob',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()
